package com.jiuqi.bi.irp.inforesource.manager;

import com.jiuqi.bi.i18n.locales.I18nLocales;
import com.jiuqi.bi.irp.core.enums.BooleanEnum;
import com.jiuqi.bi.irp.core.enums.DataTypeEnum;
import com.jiuqi.bi.irp.core.item.DBDataStructure;
import com.jiuqi.bi.text.DateFormatEx;
import com.jiuqi.bi.text.DateFormatTransfer;
import com.jiuqi.bi.util.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;

@Service
public class IResStructureDataValueVaildator {

    private final static DecimalFormat FORMAT_DOUBLE = new DecimalFormat("#.#########");


    /**
     * 获取表格列数据
     *
     * @param cell   表格cell
     * @return 返回值
     * @throws Exception
     */
    Object getAndValidCell(Cell cell,DBDataStructure firstAttribute, DBDataStructure secondAttribute) throws Exception {

        //校验是否可以为空
        Integer isPrimaryKey = secondAttribute.getIsPrimaryKey(); //是否主键
        Integer isNull = secondAttribute.getIsNull();
        if (isNull == BooleanEnum.NO.id() && isPrimaryKey == BooleanEnum.NO.id()) {
            String stringValue = getCellValueAsString(cell);
            if (StringUtils.isEmpty(stringValue.trim())) {
                throw new Exception("数据不能为空！");
            }
        } else if (cell == null)
            return null;


        if (firstAttribute.getDataType() == DataTypeEnum.BOOLEAN.id()) {
            //处理布尔类型
            return handleBooleanCell(cell);
        } else if (secondAttribute.getDataType() == DataTypeEnum.FLOAT.id()) {
            //处理浮点类型
            return handleFloatCell(cell, secondAttribute);
        } else if (secondAttribute.getDataType() == DataTypeEnum.INTEGER.id()
                ||
                secondAttribute.getDataType() == DataTypeEnum.LONG.id()) {
            //处理数值类型
            return handleNumberCell(cell, secondAttribute);
        } else if (secondAttribute.getDataType() == DataTypeEnum.STRING.id()
                ||
                secondAttribute.getDataType() == DataTypeEnum.UNKNOW.id()
                ||
                secondAttribute.getDataType() == DataTypeEnum.BLOB.id()) {
            //处理字符类型
            return handleStringCell(cell, secondAttribute);
        } else if (secondAttribute.getDataType() == DataTypeEnum.DATE.id()) {
            //处理时期类型
            return handleDateCell(cell);
        }
        return null;
    }

    private String getCellValueAsString(Cell cell) {
        if (cell == null) {
            return "";
        }

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                return String.valueOf(cell.getNumericCellValue());
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            case BLANK:
                return "";
            default:
                return "";
        }
    }

    void validNormalValue(Object value,DBDataStructure firstAttribute, DBDataStructure secondAttribute) throws Exception {
        String curValue = (String) value;

        //校验是否可以为空
        Integer isPrimaryKey = secondAttribute.getIsPrimaryKey(); //是否主键
        Integer isNull = secondAttribute.getIsNull();
        if (isNull == BooleanEnum.NO.id()) {
            if (value == null) {
                if (isPrimaryKey == BooleanEnum.YES.id())
                    throw new Exception("主键不能为空");
                else
                    throw new Exception("数据不能为空！");
            } else {
                if (StringUtils.isEmpty(curValue.trim())) {
                    if (isPrimaryKey == BooleanEnum.YES.id())
                        throw new Exception("主键不能为空");
                    else
                        throw new Exception("数据不能为空！");
                }
            }
        }

        if (firstAttribute.getDataType() == DataTypeEnum.BOOLEAN.id()) {
            //处理布尔类型
            handleBooleanValue(curValue);
        } else if (secondAttribute.getDataType() == DataTypeEnum.FLOAT.id()) {
            //处理浮点类型
            handleFloatValue(secondAttribute,curValue);
        } else if (secondAttribute.getDataType() == DataTypeEnum.INTEGER.id()
                ||
                secondAttribute.getDataType() == DataTypeEnum.LONG.id()) {
            //处理数值类型
            handleNumberValue(secondAttribute,curValue);
        } else if (secondAttribute.getDataType() == DataTypeEnum.STRING.id()
                ||
                secondAttribute.getDataType() == DataTypeEnum.UNKNOW.id()
                ||
                secondAttribute.getDataType() == DataTypeEnum.BLOB.id()) {
            //处理字符类型
            handleStringValue(secondAttribute,curValue);
        } else if (secondAttribute.getDataType() == DataTypeEnum.DATE.id()) {
            //处理时期类型
            handleDateValue(curValue);
        }
    }


    /**
     * 处理布尔类型
     *
     * @param cell
     * @return
     * @throws Exception
     */
    private Object handleBooleanCell(Cell cell) throws Exception {
        if (cell.getCellType() == CellType.NUMERIC) {
            if (cell.getNumericCellValue() > 0)
                return BooleanEnum.YES.id();
            else
                return BooleanEnum.NO.id();
        }  else if (cell.getCellType() == CellType.BOOLEAN) {
            boolean valueBoolean = cell.getBooleanCellValue();
            if (valueBoolean) return BooleanEnum.YES.id();
            else  return BooleanEnum.NO.id();
        } else if (cell.getCellType() == CellType.STRING) {
            String valueStr = cell.getStringCellValue();
            return handleBooleanValue(valueStr);
        } else {
            throw new Exception("数据类型与数据结构中数据类型不一致！");
        }
    }

    private  Object handleBooleanValue(String valueStr) throws Exception {
        if (StringUtils.isEmpty(valueStr)) {
            return "";
        }

        String regex = "^-?\\d+$";

        if ("true".equalsIgnoreCase(valueStr) || "是".equals(valueStr) || (valueStr.matches(regex) && Integer.parseInt(valueStr) > 0)) {
            return BooleanEnum.YES.id();
        } else if ("false".equalsIgnoreCase(valueStr) || "否".equals(valueStr) || (valueStr.matches(regex) && Integer.parseInt(valueStr) <= 0)) {
            return BooleanEnum.NO.id();
        } else {
            throw new Exception("数据类型与数据结构中数据类型不一致！");
        }
    }


    /**
     * 处理浮点类型
     *
     * @param cell
     * @param fieldStructure
     * @return
     * @throws Exception
     */
    private Object handleFloatCell(Cell cell, DBDataStructure fieldStructure) throws Exception {
        if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.STRING) {
            String valueStr = "";
            if (cell.getCellType() == CellType.STRING) {
                valueStr = cell.getStringCellValue();
            } else {
                double value = cell.getNumericCellValue();
                valueStr = FORMAT_DOUBLE.format(value);
            }

            return handleFloatValue(fieldStructure, valueStr);
        } else {
            throw new Exception("数据类型为浮点型！");
        }
    }

    private  String handleFloatValue(DBDataStructure fieldStructure, String valueStr) throws Exception {
        //校验长度和小数位
        int entireLength = fieldStructure.getPrecision();
        int decimalLength = fieldStructure.getScale();
        String floatPart = "";
        //可能瞎填，判断字符能否转换成浮点
        if (StringUtils.isNotEmpty(valueStr)) {
            try {
                Double.valueOf(valueStr);
            } catch (Exception e) {
                throw new Exception("数据类型应为浮点型！");
            }

            if (valueStr.contains(".")) {
                String[] temp = valueStr.split("\\.");
                if (temp.length == 2)  floatPart = temp[1];
            }
            if (valueStr.length() > entireLength) {
                throw new Exception("为浮点型，最大长度为" + entireLength + "！");
            }
            if (floatPart.length() > decimalLength) {
                throw new Exception("为浮点型,小数位为" + decimalLength + "！");
            }

            if (entireLength == 20 && decimalLength == 8 && Math.abs(Double.parseDouble(valueStr)) > Math.pow(10, 12)){
                throw new Exception("为浮点型,精度为20,小数位为8,其四舍五入后的绝对值应该小于10^12");
            }

            return valueStr;
        }else
            return "";
    }


    /**
     * 处理数值类型
     *
     * @param cell
     * @param fieldStructure
     * @return
     * @throws Exception
     */
    private Object handleNumberCell(Cell cell, DBDataStructure fieldStructure) throws Exception {
        if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.STRING) {
            String valueStr = "";
            if (cell.getCellType() == CellType.NUMERIC) {
                Long value = (long) cell.getNumericCellValue();
                valueStr = value.toString();
            } else if (StringUtils.isNotEmpty(cell.getStringCellValue())) {
                valueStr = cell.getStringCellValue();
            }

            return handleNumberValue(fieldStructure, valueStr);

        } else {
            DataTypeEnum dataTypeEnum = DataTypeEnum.parseId(fieldStructure.getDataType().intValue());
            throw new Exception("数据类型为" + dataTypeEnum.title() + "型！");
        }
    }

    private String handleNumberValue(DBDataStructure fieldStructure, String valueStr) throws Exception {
        //可以为空的值跳过校验
        if (StringUtils.isEmpty(valueStr)) return "";


        // 正则表达式匹配整数（包括负数）
        String regex = "^-?\\d+$";
        if (valueStr.matches(regex)) {
            if (valueStr.length() > fieldStructure.getPrecision() && fieldStructure.getPrecision() != 0) {
                throw new Exception("数据超长，最大长度为" + fieldStructure.getPrecision() + "！");
            }
        } else {
            throw new Exception("数据类型与数据结构中数据类型不一致！");

        }

        return valueStr;
    }

    /**
     * 处理字符类型
     *
     * @param cell
     * @param fieldStructure
     * @return
     * @throws Exception
     */
    private Object handleStringCell(Cell cell, DBDataStructure fieldStructure) throws Exception {
        if (cell.getCellType() == CellType.NUMERIC) {
            cell.setCellType(CellType.STRING);
        }
        String value = cell.getStringCellValue();
        return handleStringValue(fieldStructure, value);

    }

    private  String handleStringValue(DBDataStructure fieldStructure, String value) throws Exception {

        if (StringUtils.isEmpty(value)) return "";

        if (value.length() > fieldStructure.getPrecision() && fieldStructure.getDataType() != DataTypeEnum.BLOB.id()) {
            throw new Exception("数据超长，最大长度为" + fieldStructure.getPrecision() + "！");
        }
        return value;
    }

    /**
     * 处理时期类型
     *
     * @param cell
     * @return
     * @throws Exception
     */
    private Object handleDateCell(Cell cell) throws Exception {
        String value = "";
        if (cell.getCellType() == CellType.NUMERIC) {
            Date dateCellValue = cell.getDateCellValue();
            if (dateCellValue != null) {
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                value = format.format(dateCellValue);
            }
        } else {
            value = cell.getStringCellValue();
        }

        return handleDateValue(value);
    }

    private Object handleDateValue(String value) throws Exception {
        if (StringUtils.isNotEmpty(value)) {
            String formatDateTime = formatDateTime("yyyy-MM-dd", value);
            if (StringUtils.isEmpty(formatDateTime)) {
                throw new Exception("请按照日期格式yyyy-mm-dd填写数据");
            }
            try {
                LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            } catch (Exception e) {
                throw new Exception("为日期类型，请按照日期格式yyyy-mm-dd输入正确日期");
            }
            return value;
        }else
            return "";
    }

    /**
     * 格式化时期
     *
     * @param showPattern 时期格式
     * @param value       当前值
     * @return 返回格式化的数据
     */
    String formatDateTime(String showPattern, String value) {
        String formatkey = "";
        try {
            Locale locale = I18nLocales.getCurrentLocale();
            String showPattern4locale = DateFormatTransfer.transfer(showPattern, locale);
            formatkey = new DateFormatEx(showPattern4locale, locale).format(new DateFormatEx(showPattern).parse(value));
        } catch (Exception e) {
            return "";
        }

        return formatkey;
    }

}
